﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Jb.Domain;
using Jb.Web.ViewModels;
using AutoMapper;
using Jb.Common.Xml;
using Jb.Common.Extensions;
using Jb.Common.DB;
using System.IO;
using Jb.Common.Mail;

namespace Jb.Web.Utility
{
    public static class WebUtil
    {
        /// <summary>
        /// Populates the Session for an previously Authenticated User
        /// </summary>
        public static void ReLoginUser()
        {
            if (HttpContext.Current.User.Identity.IsAuthenticated && SessionCache.CurrentUser == null)
            {
                String userName = HttpContext.Current.User.Identity.Name;
                if (!userName.IsNullOrEmpty())
                {
                    JbEntities context = new JbEntities();
                    User user = context.Users.Include("Contact").Include("JobSeeker").Include("Group")
                        .FirstOrDefault(U => String.Compare(U.UserName, userName, true) == 0);
                    if (user != null)
                    {
                        ///Load Group and Group Permissions                                
                        //user.UserGroup = groupDAO.Get(user.GroupCode);                
                        UserViewModel userViewModel = null;
                        userViewModel = Mapper.Map<User, UserViewModel>(user, userViewModel);

                        ///Load Compnay Information, if Exists
                        //LoadCompanyInfo(userViewModel, user, context);
                        SessionCache.CurrentUser = userViewModel;
                        SessionCache.RefreshUserInfo();
                    }
                }
            }
        }        

        public static String GetBooleanLabelID(String elementName, bool isEnabled)
        {
            if (isEnabled)
                return String.Format("{0}{1}_Yes", AppConstants.UI.DYNAMIC_CONTROL_PREFIX, elementName);
            else
                return String.Format("{0}{1}_No", AppConstants.UI.DYNAMIC_CONTROL_PREFIX, elementName);
        }
                
        /// <summary>
        /// Gets Formated Data for Display Purpose
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static String FormatData(object data)
        {
            if (data.GetType() == typeof(String))
                return FormatText(NullHandler.GetString(data));
            else if (data.GetType() == typeof(DateTime))
                return NullHandler.GetDateTime(data).ToString(AppConstants.ValueOf.DATE_FROMAT_DISPLAY);
            else if (data.GetType() == typeof(decimal))
                return String.Format(AppConstants.ValueOf.DECIMAL_FORMAT, NullHandler.GetDecimal(data));
            else if (data.GetType() == typeof(bool))
                return NullHandler.GetBoolean(data) ? "Yes" : "No";
            else
                return NullHandler.GetString(data);
        }

        /// <summary>
        /// HtmlEncodes text and replaces newline with <br/> tags to create newline in web pages
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        public static String FormatText(String text)
        {
            return text.HtmlEncode().Replace(Environment.NewLine, "<br />").Replace("\n", "<br />");
        }

        /// <summary>
        /// Reads HTML Template from File System
        /// </summary>
        /// <param name="templateFileName"></param>
        /// <returns></returns>
        public static String ReadEmailTemplate(String templateFileName)
        {
            String filePath = HttpContext.Current.Server.MapPath(templateFileName);
            if (File.Exists(filePath))
                return File.ReadAllText(filePath);

            return String.Empty;
        }
        /// <summary>
        /// Gets Currently Hosted Domain Address
        /// </summary>
        /// <returns></returns>
        public static String GetDomainAddress()
        {
            Uri uri = HttpContext.Current.Request.Url;
            String url = String.Format("{0}{1}{2}{3}", uri.Scheme, Uri.SchemeDelimiter, uri.Host, uri.Port == 80 ? String.Empty : ":" + uri.Port);
            //return String.Format("http://{0}", HttpContext.Current.Request.Url.Host);
            return url;
        }

        /// <summary>
        /// Sends an email using the core email sending functions. It logs failed emails into the database with server error messages.
        /// </summary>
        /// <param name="fromEmail"></param>
        /// <param name="toEmail"></param>
        /// <param name="bcc"></param>
        /// <param name="cc"></param>
        /// <param name="subject"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        public static bool SendMail(String fromEmail, String toEmail, String bcc, String cc, String subject, String message)
        {
            bool isSent = false;
            try
            {
                isSent = MailManager.SendMail(toEmail, cc, bcc, fromEmail, subject, message);
            }
            catch (Exception ex)
            {
                ///Log Failed Message
                JbEntities context = new JbEntities();
                EmailMessage email = new EmailMessage();
                email.Subject = subject;
                email.FromEmail = fromEmail;
                email.ToEmail = toEmail;
                email.CC = cc;
                email.BCC = bcc;
                email.Message = message;
                email.IsSent = false;
                email.Created = DateTime.Now;
                email.AttemptedOn = DateTime.Now;
                email.ErrorMessage = ex.Message;
                email.StackTrace = ex.StackTrace;
                if (SessionCache.CurrentUser != null)
                    email.UserID = SessionCache.CurrentUser.ID;
                context.AddToEmailMessages(email);
                context.SaveChanges();
            }
            return isSent;
        }

        /// <summary>
        /// Checks Whether an Uploaded file is a Valid Image File Or Not
        /// </summary>
        /// <param name="httpPostedFile"></param>
        /// <returns></returns>
        public static bool IsValidImageFile(HttpPostedFileBase httpPostedFile)
        {
            if (httpPostedFile.ContentLength > 0)
            {
                string extension = Path.GetExtension(httpPostedFile.FileName);
                return IsValidImageFileExtension(extension);
            }
            return false;
        }
        /// <summary>
        /// Checks for a valid file extension for an image.
        /// </summary>
        /// <param name="extension"></param>
        /// <returns></returns>
        private static bool IsValidImageFileExtension(string extension)
        {
            if (String.Compare(extension, ".jpg", true) == 0)
                return true;
            else if (String.Compare(extension, ".jpeg", true) == 0)
                return true;
            else if (String.Compare(extension, ".gif", true) == 0)
                return true;
            else if (String.Compare(extension, ".png", true) == 0)
                return true;
            return false;
        }

        /// <summary>
        /// Gets Product Dynamic Property Value from a Prepopulated Dynamic Property Collection
        /// </summary>
        /// <param name="groupName"></param>
        /// <param name="propertyName"></param>
        /// <param name="product"></param>
        /// <returns></returns>
        public static String GetPropertyValue(String groupName, String propertyName, ViewModels.ZGL.Category.Category dynamicProperties)
        {
            if (dynamicProperties != null && dynamicProperties.Group != null)
            {
                ViewModels.ZGL.Category.ProductGroup group = dynamicProperties.Group.FirstOrDefault(G => G.Name == groupName);
                if (group != null)
                {
                    ViewModels.ZGL.Category.ProductGroupProperty property = group.Property.FirstOrDefault(P => P.Name == propertyName);
                    if (property != null)
                        return property.Value;
                }
            }
            return "N/A";
        }

        /// <summary>
        /// Maps category definition to View Model
        /// </summary>
        /// <param name="jobViewModel"></param>
        /// <param name="ZGL"></param>
        public static void MapZGL(JobViewModel jobViewModel, String ZGL)
        {
            //if (!jobViewModel.DynamicProperties.IsNullOrEmpty())
            if(!ZGL.IsEmpty())
            {
                Jb.Web.ViewModels.ZGL.Category.Category categoryZGL = XmlHelper.ToObject<Jb.Web.ViewModels.ZGL.Category.Category>(ZGL);
                ///If Edit Mode of a Product
                if (!jobViewModel.DynamicProperties.IsNullOrEmpty())
                {
                    Jb.Web.ViewModels.ZGL.Product.Product productDefinition = XmlHelper.ToObject<Jb.Web.ViewModels.ZGL.Product.Product>(jobViewModel.DynamicProperties);
                    foreach (Jb.Web.ViewModels.ZGL.Category.ProductGroup group in categoryZGL.Group)
                    {
                        foreach (Jb.Web.ViewModels.ZGL.Category.ProductGroupProperty property in group.Property)
                        {
                            setPropertyValue(property, productDefinition.Property);
                        }
                    }
                }
                jobViewModel.CategoryZGL = categoryZGL;
            }
        }

        private static void setPropertyValue(ViewModels.ZGL.Category.ProductGroupProperty property, List<ViewModels.ZGL.Product.ProductProperty> sourceProperties)
        {
            ViewModels.ZGL.Product.ProductProperty sourceProperty = sourceProperties.FirstOrDefault(P => String.Compare(P.Name, property.Name, true) == 0);
            if (sourceProperty != null)
                property.Value = sourceProperty.Value;
        }

        /// <summary>
        /// Builds a Blank JobSeeker Object along with a Address object.
        /// </summary>
        /// <param name="email"></param>
        /// <returns></returns>
        public static JobSeeker BuildBlankJobSeeker(String email, int userID)
        {
            JobSeeker jobSeeker = new JobSeeker();
            jobSeeker.HasProfileCompleted = false;
            jobSeeker.CreatedOn = DateTime.Now;
            jobSeeker.ModifiedOn = DateTime.Now;
            jobSeeker.Name = AppConstants.ValueOf.UNKNOWN;
            jobSeeker.DateOfBirth = AppConstants.ValueOf.DEFAULT_DATE_OF_BIRTH;
            jobSeeker.Gender = "M";
            
            //TODO: UniqueIdentifier Issue Need to Change for MySQL
            jobSeeker.ActivationKey = System.Guid.NewGuid();
            //jobSeeker.ActivationKey = System.Guid.NewGuid().ToString();
            
            jobSeeker.Address = new Address();
            jobSeeker.Address.ZipCode = AppConstants.ValueOf.UNKNOWN;
            jobSeeker.Address.AddressType = (int)AddressType.Permanent;
            jobSeeker.Address.Email = email;
            jobSeeker.Address.CreatedOn = jobSeeker.Address.ModifiedOn = DateTime.Now;
            jobSeeker.ModifiedBy = userID;
            jobSeeker.Address.ModifiedBy = userID;

            return jobSeeker;
        }

        /// <summary>
        /// Gets the IP Address of the Requested Client
        /// </summary>
        /// <returns></returns>
        public static string GetRemoteIPAddress()
        {
            return HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
        }

        /// <summary>
        /// Gets the Session Key of currently executing request
        /// </summary>
        /// <returns></returns>
        public static string GetSessionKey()
        {
            if (HttpContext.Current.Session != null)
                return HttpContext.Current.Session.SessionID;
            return String.Empty;
        }

        /// <summary>
        /// Gets the physical file path of a Resume
        /// </summary>
        /// <param name="jobSeekerID"></param>
        /// <param name="resumeFileName"></param>
        /// <returns></returns>
        public static string GetResumePath(int jobSeekerID, String resumeFileName)
        {
            return System.IO.Path.Combine(HttpContext.Current.Server.MapPath(AppConstants.Directories.RESUMES), jobSeekerID.ToString(), resumeFileName);
        }

        /// <summary>
        /// Determines whether the current request is from a Mobile Device
        /// </summary>
        /// <returns></returns>
        public static bool IsMobileRequest()
        {
            if (ConfigReader.SimulateMobileRequest)
                return true;
            HttpRequest request = HttpContext.Current.Request;
            if (request.Browser["IsMobileDevice"] == "true" || request.UserAgent.ToUpper().Contains("MIDP") || request.UserAgent.ToUpper().Contains("CLDC"))
                return true;

            return false;
        }

        /// <summary>
        /// Gets a boolean value depending on the key of the querystring.
        /// Strings that will be evaluated to boolean True are as follows:
        /// <para>
        /// true, True, yes, Yes, y, Y, 1
        /// </para>
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static bool GetQueryStringBoolean(String key)
        {
            String value = HttpContext.Current.Request[key];
            return value.ToBoolean();
        }

        public static int GetQueryStringInt(String key)
        {
            String value = HttpContext.Current.Request[key];
            return value.ToInt();
        }

        public static String GetQueryStringValue(String key)
        {
            String value = HttpContext.Current.Request[key];
            return value;
        }

        /// <summary>
        /// Gets Completed External Absolute URL. 
        /// Checks whether the URL starts with http or https, if not then adds http:// at the
        /// Begining of the URL to make it complete
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public static String GetCompleteUrl(String url)
        {
            return url.ToLower().StartsWith("http://") || url.ToLower().StartsWith("https://") ? url : String.Format("http://{0}", url);
        }

        /// <summary>
        /// Compares equality between two variables, one can be string guid and another can be guid object of course both of them can be guid
        /// </summary>
        /// <param name="identifier"></param>
        /// <param name="guid"></param>
        /// <returns></returns>
        public static bool IsGuidEqual(object identifier, Guid guid)
        {
            if (identifier.GetType() == guid.GetType())
                return (Guid)identifier == guid;
            else if (identifier.GetType() == typeof(String))
                return identifier.ToString().ToGuid() == guid;

            return false;
        }

        /// <summary>
        /// Gets Shortened Job Description
        /// </summary>
        /// <param name="description"></param>
        /// <returns></returns>
        public static string GetFormattedJobDescription(String description)
        {
            if (description.WordCount() > 40)
                return String.Format("{0} ...", description.GetWords(40));

            return description;
        }
    }
}